package org.example.service.RedPackage;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.java.Log;
import org.example.bean.RedPacketActivity;
import org.example.bean.UserRedPacket;
import org.example.dao.AddressMapper;
import org.example.dao.RedPacketMapper;
import org.example.dao.UserRedPacketMapper;
import org.example.enums.RedPacketStatus;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@AllArgsConstructor
@Log
public class RedPacketServiceImpl implements RedPacketService {
    private final RedPacketMapper redPacketMapper;  //红包创建表的操作
    private final RedissonClient redissonClient;  //实现分布式锁
    private final UserRedPacketMapper userRedPacketMapper;  //用户抢红包表的操作
    private final UserRedPacketService userRedPacketService;  //用户抢红包表的操作

    //根据活动id查询红包状态
    @Override
    public RedPacketStatus getRedPacketStatus(Integer redPacketId) {
        RedPacketActivity redPacketActivity = redPacketMapper.selectById(redPacketId);
        //没有这个红包活动
        if(redPacketActivity==null){
            return null;
        }
        //活动未开始
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(redPacketActivity.getStart_time())) {
            redPacketActivity.setStatus(0);
            redPacketMapper.updateById(redPacketActivity);
            return RedPacketStatus.NOT_STARTED;
        }

// 活动结束了或者红包被抢完了
        if (now.isAfter(redPacketActivity.getEnd_time()) ||
                redPacketActivity.getTotal_packets() == 0) {
            redPacketActivity.setStatus(2);
            redPacketMapper.updateById(redPacketActivity);
            return RedPacketStatus.FINISHED;
        }
        //活动进行中
        redPacketActivity.setStatus(1);
        redPacketMapper.updateById(redPacketActivity);
        return RedPacketStatus.AVAILABLE;
    }

    //查找最新活动信息
    @Override
    public RedPacketActivity getRedPacketActivity() {
        return redPacketMapper.getLatestRedPacketActivity();
    }

    @Override
    // 抢红包
    public GrabResult grabRedPacket(Integer userId, Integer redPacketId) {
        // 获取分布式锁，防止超卖
        RLock lock = redissonClient.getLock("red_packet:" + redPacketId);
        try {
            // 尝试加锁，最多等待100毫秒，上锁后30秒自动解锁
            if (lock.tryLock(100, 30000, TimeUnit.MILLISECONDS)) {
                // 再次检查红包状态
                RedPacketStatus status = getRedPacketStatus(redPacketId);
                if (status != RedPacketStatus.AVAILABLE) {
                    return new GrabResult(false, status.getMessage(), null);
                }

                //检查用户是否已经领取过
                if (userRedPacketService.findByUserIdAndActiveId(userId, redPacketId) != null) {
                    return new GrabResult(false, "您已经抢过这个红包了", null);
                }

                // 获取红包,判断红包是否存在
                RedPacketActivity redPacket = redPacketMapper.selectById(redPacketId);
                if (redPacket == null) {
                    throw new RuntimeException("红包不存在");
                }


                // 计算抢到的金额(这里使用随机算法)
                Double amount = calculateGrabAmount(redPacket);

                // 保存记录
                UserRedPacket userRedPacket = new UserRedPacket();
                userRedPacket.setUser_id(userId);
                userRedPacket.setActivity_id(redPacketId);
                userRedPacket.setAmount(amount);
                userRedPacketMapper.insert(userRedPacket);

                // 更新红包剩余数量和金额
                redPacket.setTotal_packets(redPacket.getTotal_packets() - 1);
                redPacket.setTotal_amount(redPacket.getTotal_amount() - amount);
                redPacketMapper.updateById(redPacket);

                return new GrabResult(true, "抢红包成功", amount);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return new GrabResult(false, "系统繁忙，请稍后再试", null);
    }

    //创建红包活动
    @Override
    public RedPacketActivity createRedPacketActivity(RedPacketActivity redPacketActivity) {
        redPacketActivity.setStatus(0);
        redPacketMapper.insert(redPacketActivity);
        return redPacketActivity;
    }

    //查询所有的活动信息
    @Override
    public List<RedPacketActivity> getAllRedPacketActivity() {
        //查询所有的活动信息，并检查活动状态
        LambdaQueryWrapper<RedPacketActivity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(RedPacketActivity::getId);
        List<RedPacketActivity> redPacketActivityList = redPacketMapper.selectList(queryWrapper);
        //检查活动状态
        for (RedPacketActivity redPacketActivity : redPacketActivityList) {
            RedPacketStatus redPacketStatus = getRedPacketStatus(redPacketActivity.getId());
            redPacketActivity.setStatus(redPacketStatus.getCode());
        }
        return redPacketActivityList;
    }

    // 计算抢到的金额(二倍均值法)
    private Double calculateGrabAmount(RedPacketActivity redPacket) {
        if (redPacket.getTotal_packets() == 1) {
            return redPacket.getTotal_amount();
        }

        Random random = new Random();
        // 计算最大可抢金额 = 剩余金额 / 剩余个数 * 2
        Double max = redPacket.getTotal_amount()/redPacket.getTotal_packets()*2;

        // 随机金额范围: 0.01 ~ max
        Double amount = random.nextDouble() * max + 0.01;

        // 确保至少0.01元
        amount = Math.max(amount, 0.01);
        return amount;
    }
}
